﻿using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using Oxage.Common;
using Oxage.Simulator;

namespace Oxage.Controls
{
	public class VectorSimulationCanvas : Control, IStepDriver
	{
		#region Members
		private PathFigure figure;
		#endregion

		#region Constructor
		public VectorSimulationCanvas()
		{
			this.DefaultStyleKey = typeof(VectorSimulationCanvas);
			var geometry = new PathGeometry();
			figure = new PathFigure();
			figure.StartPoint = new Point(0, 0);
			geometry.Figures.Add(figure);
			this.Geometry = geometry;
		}
		#endregion

		#region Template
		protected Grid RootElement;

		public override void OnApplyTemplate()
		{
			RootElement = GetTemplateChild("RootElement") as Grid;

			base.OnApplyTemplate();
		}
		#endregion

		#region Dependency properties

		#region Geometry
		public PathGeometry Geometry
		{
			get { return (PathGeometry)GetValue(GeometryProperty); }
			set { SetValue(GeometryProperty, value); }
		}

		public static readonly DependencyProperty GeometryProperty = DependencyProperty.Register("Geometry", typeof(PathGeometry), typeof(VectorSimulationCanvas), new PropertyMetadata(GeometryChanged));

		private static void GeometryChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
		}
		#endregion

		#region StrokeThickness
		public double StrokeThickness
		{
			get { return (double)GetValue(StrokeThicknessProperty); }
			set { SetValue(StrokeThicknessProperty, value); }
		}

		public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register("StrokeThickness", typeof(double), typeof(VectorSimulationCanvas), new PropertyMetadata(StrokeThicknessChanged));

		private static void StrokeThicknessChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
		}
		#endregion

		#region Stroke
		public Brush Stroke
		{
			get { return (Brush)GetValue(StrokeProperty); }
			set { SetValue(StrokeProperty, value); }
		}

		public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register("Stroke", typeof(Brush), typeof(VectorSimulationCanvas), new PropertyMetadata(StrokeChanged));

		private static void StrokeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
		}
		#endregion

		#region Protected methods
		protected void AddSegment(Point3D point)
		{
			ViewHelper.Dispatch(() =>
			{
				var p = new Point(point.X, point.Y);
				figure.Segments.Add(new LineSegment(p, true));

				//OnPropertyChanged("Geometry");

				var value = this.Geometry;
				this.Geometry = null;
				this.Geometry = value;

				//Thread.Sleep(100);
			});
		}
		#endregion

		#endregion

		#region Public methods
		public void Clear()
		{
			ViewHelper.Dispatch(() =>
			{
				//Reset cursor position
				this.cursor = new NPoint();

				//Clear all drawings
				figure.Segments.Clear();

				//OnPropertyChanged("Geometry");

				//Request redraw
				var value = this.Geometry;
				this.Geometry = null;
				this.Geometry = value;
			});
		}
		#endregion

		#region IStepDriver Members
		NPoint IStepDriver.Cursor
		{
			get
			{
				return this.cursor;
			}
		}
		private NPoint cursor = new NPoint();

		public IList<NPoint> ReferencePoints
		{
			get
			{
				return this.referencePoints;
			}
		}
		private List<NPoint> referencePoints = new List<NPoint>();

		public void Step(NPoint delta)
		{
			var d = delta.GetSignum();
			var driver = this as IStepDriver;
			foreach (var dim in d.GetKeys())
			{
				driver.Cursor[dim] += d[dim];
			}

			var point = driver.Cursor.GetPoint3D();
			AddSegment(point);
		}
		#endregion
	}
}
